import { useEffect, useMemo, useState } from 'react'
import examPaperApi from './api/index'
import { Button, Flex } from 'antd'
import './index.scss'
import dayjs from 'dayjs'
import QuestionType from '@/component/common/questionType'
import Countdown from 'antd/es/statistic/Countdown'
import { useMessageApi } from '@/component/context/messageContext/message'
import { useNavigate } from 'react-router-dom'
import { ZN_alphabets } from '@/config/globalConfig'
import { MyDialog } from '@/component/common/myDialog'
export default function Exam() {
  const [examPaper, setExamPaper] = useState<any[]>([])
  const [exam, setExam] = useState<any>({})
  const [config, setConfig] = useState<any>({})
  const messageApi = useMessageApi()
  const [ddl, setDdl] = useState<any>(null)
  const [isShowSubmit, setIsShowSubmit] = useState<boolean>(false)
  const [isShowLimitJump, setIsShowLimitJump] = useState<boolean>(false)
  const [noAnswer, setNoAnswer] = useState<any[]>([])
  const navigate = useNavigate()

  const getExamPaper = async () => {
    await examPaperApi.getExamPaper().then((res: any) => {
      setExamPaper(JSON.parse(res.examPaper.content_no_answer))
      setExam(res.exam)
    })
  }

  useEffect(() => {
    let timer: any = null
    const checkConfig = async () => {
      await examPaperApi.checkConfig().then((res: any) => {
        /**
         * set配置
         */
        setConfig(res.exam)

        /**
         * 同步倒计时
         */
        const begin_duration = dayjs(res.exam.begin_time).add(
          res.exam.duration,
          'minute'
        )
        if (begin_duration.isBefore(dayjs(res.exam.end))) {
          if (begin_duration.isBefore(dayjs())) {
            clearTimeout(timer)
            messageApi.error('考试已结束')
            navigate('/finished')
            return
          }
          setDdl(begin_duration.toISOString())
        } else {
          setDdl(res.exam.end)
        }
        if (dayjs(res.exam.end).isBefore(dayjs())) {
          clearTimeout(timer)
          messageApi.error('考试已结束')
          navigate('/login')
          return
        }

        if (Number(res.exam.is_submit) === 1) {
          clearTimeout(timer)
          messageApi.error('考试已提交')
          navigate('/finished')
          return
        }
        /**
         * 递归下一轮
         */
        timer = setTimeout(() => {
          checkConfig()
        }, 5000)
      })
    }
    getExamPaper()
    checkConfig()
    return () => {
      clearTimeout(timer)
    }
  }, [messageApi, navigate])

  /**
   * 试卷内容
   * @returns
   */
  const ExamPaper = () => {
    return (
      <Flex vertical gap="2rem">
        {examPaper.map((item, itemIndex) => {
          return (
            <Flex
              vertical
              gap="1rem"
              key={itemIndex}
              className="exam-content"
              style={{ width: '80%' }}>
              <div className="type-name">
                <h3>
                  {ZN_alphabets[itemIndex]}. {item.title}
                </h3>
              </div>
              <Flex gap="1rem" vertical style={{ paddingLeft: '1rem' }}>
                {item.ques.map((ques: any, index: any) => {
                  return (
                    <Flex key={index}>
                      <span className="index">{index + 1}.</span>
                      <QuestionType
                        id={`ques${ques.id}`}
                        content={ques}
                        score={ques.score}
                        onChange={(value: any) => {
                          setNoAnswer((oldV) => {
                            let temp: any[] = []
                            oldV.forEach((ele) => {
                              if (ele !== String(ques.id)) {
                                temp.push(ele)
                              }
                            })
                            return [...temp]
                          })
                          setExamPaper((oldV) => {
                            oldV[itemIndex].ques[index].answer = value.answer
                            return [...oldV]
                          })
                        }}
                        state="TODO"></QuestionType>
                    </Flex>
                  )
                })}
              </Flex>
            </Flex>
          )
        })}
      </Flex>
    )
  }

  /**
   * 提交方法
   */
  const submit = async () => {
    await examPaperApi.submitExamPaper(examPaper).then((res: any) => {
      if (res?.code === 200) {
        messageApi.success('提交成功')
        navigate('/finished')
      } else {
        messageApi.error(res)
        setTimeout(() => {
          navigate('/wait')
        }, 1000)
      }
    })
  }

  /**
   * 锚点控制板
   * @returns
   */
  const ControlPanel = useMemo(() => {
    const goAnchor = (id: string) => {
      const tragetElem = document.getElementById(id)
      if (!tragetElem) {
        return
      }
      const tragetElemPostition = tragetElem.offsetTop - window.innerHeight / 3

      let scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop
      const step = function () {
        let distance = tragetElemPostition - scrollTop
        scrollTop = scrollTop + distance / 5
        if (Math.abs(distance) < 1) {
          window.scrollTo(0, tragetElemPostition)
        } else {
          window.scrollTo(0, scrollTop)
          setTimeout(step, 20)
        }
      }
      step()
    }
    const tosubmit = () => {
      const noAnswerArr = []
      for (let i = 0; i < examPaper.length; i++) {
        for (let j = 0; j < examPaper[i].ques.length; j++) {
          if (!String(examPaper[i].ques[j].answer).length) {
            noAnswerArr.push(String(examPaper[i].ques[j].id))
          }
        }
      }
      setNoAnswer(noAnswerArr)
      if (noAnswerArr.length) {
        messageApi.error(`您有${noAnswerArr.length}道题未作答`)
      }
      setIsShowSubmit(true)
    }
    return (
      <div className="control-panel">
        <div className="link-box-box">
          {examPaper.map((item, itemIndex) => {
            return (
              <Flex
                vertical
                gap="0.5rem"
                style={{ marginBottom: '0.8rem' }}
                key={item.title}>
                <h4>
                  {ZN_alphabets[itemIndex]}. {item.title}
                </h4>
                <Flex gap="0.5rem" wrap>
                  {item.ques.map((ques: any, index: any) => {
                    const getBackGroundColor = () => {
                      if (String(item.ques[index].answer)) {
                        if (
                          item.ques[index].answer instanceof Array &&
                          item.ques[index].answer[0].hasOwnProperty('value')
                        ) {
                          for (
                            let ji = 0;
                            ji < item.ques[index].answer.length;
                            ji++
                          ) {
                            if (
                              !String(item.ques[index].answer[ji].value).length
                            ) {
                              return 'link-box'
                            }
                          }
                        }
                        return 'link-box link-box-answer'
                      } else if (noAnswer.includes(String(ques.id))) {
                        return 'link-box link-box-nosubmit'
                      } else {
                        return 'link-box '
                      }
                    }
                    return (
                      <span
                        className={getBackGroundColor()}
                        key={ques.id}
                        onClick={() => {
                          goAnchor(`ques${ques.id}`)
                        }}>
                        {index + 1}
                      </span>
                    )
                  })}
                </Flex>
              </Flex>
            )
          })}
        </div>
        <div className="submit">
          <Button
            onClick={() => {
              tosubmit()
            }}>
            提交
          </Button>
        </div>
      </div>
    )
  }, [examPaper, messageApi, noAnswer])

  /**
   * 提交弹窗
   * @returns
   */
  const SubmitDialog = () => {
    return (
      <MyDialog
        width="30%"
        open={isShowSubmit}
        onCancel={() => setIsShowSubmit(false)}
        onClose={() => setIsShowSubmit(false)}
        onOk={() => {
          submit()
        }}>
        {noAnswer.length > 0 ? (
          <h4 style={{ color: '#F03F56' }}>您有未作答题目，确定提交吗？</h4>
        ) : (
          <h4 style={{ color: '#64C300' }}>您已全部作答</h4>
        )}
        <div>交卷后不可修改，不可重复提交！</div>
        <div>是否确定交卷？</div>
      </MyDialog>
    )
  }

  /**
   * 限制跳转弹框
   */
  const LimitJumpDialog = useMemo(() => {
    const cancelTimeDown = () => {
      setIsShowLimitJump(false)
    }
    const deadline = dayjs().add(5, 'second').toISOString()
    const sendJumpMsg = async () => {
      await examPaperApi.sendJumpMsg()
    }
    return (
      <MyDialog
        destroyOnClose
        title="系统警告"
        closable={false}
        width="90%"
        open={isShowLimitJump}
        footer={() => {
          return (
            <Button
              onClick={() => {
                cancelTimeDown()
              }}>
              确定
            </Button>
          )
        }}>
        <div className="limit-jump-content">
          <Flex
            vertical
            align="center"
            justify="space-evenly"
            className="limit-jump-msg">
            {config.jump_times >= config.limit_jump_times && (
              <div style={{ color: '#F03F56' }}>
                <h1>您的试卷已被标记为脏试卷，如遇特殊情况请联系相关负责人</h1>
              </div>
            )}
            <h1>您当前正在进行考试，请遵守协议规则，勿切换屏幕</h1>
            <h2>
              限制切屏次数：
              <span style={{ color: 'rgba(146, 143, 255, 0.8)' }}>
                {` ${config.limit_jump_times} `}
              </span>
              次 &emsp; 您已切屏：
              <span style={{ color: 'rgba(146, 143, 255, 0.8)' }}>
                {` ${config.jump_times} `}
              </span>
              次
            </h2>
            <Flex vertical justify="center" align="center">
              <h2 className="limit-jump-box">
                请在
                <div className="limit-jump-countdown">
                  倒计时：
                  <Countdown
                    value={deadline}
                    format="ss:SSS"
                    onFinish={() => {
                      sendJumpMsg()
                    }}
                  />
                </div>
                内返回，频繁切屏将导致成绩无效
              </h2>
            </Flex>
          </Flex>
        </div>
      </MyDialog>
    )
  }, [config.jump_times, config.limit_jump_times, isShowLimitJump])
  useEffect(() => {
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        if (Number(config.is_limit_jump) === 1) {
          setIsShowLimitJump(true)
        }
      }
    })
    return () => {
      document.removeEventListener('visibilitychange', () => {})
    }
  }, [config.is_limit_jump])

  return (
    <Flex className="exampaper-container" vertical>
      <Flex className="fixed-header">
        <Flex justify="center" align="center">
          <div className="countdown-box">
            <span className="countdown">倒计时：</span>
            <Countdown
              value={ddl}
              onFinish={() => {
                submit()
              }}
            />
          </div>
        </Flex>
        <div></div>
        <div></div>
      </Flex>
      <Flex justify="center" gap="2rem" style={{ padding: '3rem 0' }}>
        <div className="exampaper">
          <div className="exampaper-header">
            <h2>《{exam.name}》</h2>
            <span className="date">
              {dayjs(exam.begin).format('YYYY/MM/DD HH:MM:ss')} ~{' '}
              {dayjs(exam.end).format('YYYY/MM/DD HH:MM:ss')}
            </span>
            <span className="duration">{exam.duration}分钟</span>
          </div>
          <div className="exampaper-box">{ExamPaper()}</div>
        </div>
        {ControlPanel}
      </Flex>
      {SubmitDialog()}
      {LimitJumpDialog}
    </Flex>
  )
}
